<?php

namespace App\Traits;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;

trait GeneralService
{
    /**
     * 获取当前模型
     * @return string
     */
    abstract protected function setModel();

    /**
     * @return \Illuminate\Database\Eloquent\Model
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    protected function model()
    {
        return app()->make($this->setModel());
    }

    protected function find($id, $message = '内容不存在！', $with = [])
    {
        $info = $this->model()->with($with)->find($id);
        if (!$info) {
            throw new \Exception($message);
        }

        return $info;
    }

    protected function safeCreate($fields, $message = '创建失败')
    {
        $info = $this->model()->create($fields);
        if (!$info) {
            throw $this->createException($message);
        }

        return $info;
    }

    public function show($id, $message = '内容不存在！', $with = [])
    {
        $info = $this->find($id, $message, $with);

        return $info;
    }

    public function first($where = [], $message = '内容不存在！')
    {
        $info = $this->model()->where($where)->first();
        if (!$info) {
            throw new \Exception($message);
        }

        return $info;
    }

    public function paginate(array $conditions, $orderBys = [], $with = [])
    {
        $query = $this->model()->newQuery();
        $query = $query->when(count($with), function ($query) use ($with) {
            $query->with($with);
        });

        $this->scopeQuery($query, $conditions);

        foreach ($orderBys ?: [] as $order => $sort) {
            $query->orderBy($order, $sort);
        }

        $page_size = $conditions['page_size'] ?? 15;

        return $query->paginate($page_size);
    }

    public function all(array $conditions = [], $with = [], $orderBys = ['id'=>'desc'])
    {
        $query = $this->model()->newQuery();
        $query = $query->when(count($with), function ($query) use ($with) {
            $query->with($with);
        });

        $this->scopeQuery($query, $conditions);

        foreach ($orderBys ?: [] as $order => $sort) {
            $query->orderBy($order, $sort);
        }

        return $query->get();
    }

    public function store($fields)
    {
        $this->validateStore($fields);

        return $this->model()->create($fields);
    }

    public function update($id, $fields)
    {
        $this->validateUpdate($id, $fields);
        $info = $this->find($id);
        $info->update($fields);

        return $info;
    }

    public function destroy($id)
    {
        $info = $this->find($id);

        $info->delete();
    }

    /**
     * @param Builder $query
     */
    protected function scopeQuery(Builder $query, array $conditions)
    {
        foreach (array_filter(Arr::except($conditions, ['page', 'page_size'])) as $key => $value) {
            $query->where($key, $value);
        }
        // 角色id
//        if (!empty($conditions['role_id'])) {
//            $query->where('role_id', $conditions['role_id']);
//        }

        // 关键字(eg: 创建人)
//        if (!empty($conditions['keyword'])) {
//            $query->where('realname', 'LIKE', "%{$conditions['keyword']}%");
//        }
    }

    protected function scopeWhere(Builder $query, array $conditions)
    {
        $this->scopeWhereCondition($query, $conditions, "=");
    }

    protected function scopeWhereIn(Builder $query, array $conditions)
    {
        foreach (array_filter($conditions) as $key => $value) {
            $query->whereIn($key, $value);
        }
    }

    protected function scopeWhereLike(Builder $query, array $conditions)
    {
        foreach (array_filter($conditions) as $key => $value) {
            $query->where($key, "like", "%{$value}%");
        }
    }

    protected function scopeWhereBetween(Builder $query, array $conditions)
    {
        foreach (array_filter($conditions) as $key => $value) {
            $value = is_string($value) ? explode(',', $value) : [];
            $query->whereBetween($key, [
                Carbon::parse(Arr::first($value))->startOfDay()->toDateTimeString(),
                Carbon::parse(Arr::last($value))->endOfDay()->toDateTimeString()
            ]);
        }
    }

    protected function scopeWhereJsonContains(Builder $query, array $conditions)
    {
        foreach (array_filter($conditions) as $key => $value) {
            $query->whereJsonContains($key, $value);
        }
    }

    protected function scopeWhereInSet(Builder $query, array $conditions)
    {
        foreach (array_filter($conditions) as $key => $value) {
            $query->whereRaw('FIND_IN_SET(?, ' . $key . ')', [$value]);
        }
    }

    protected function scopeWhereCondition(Builder $query, array $data, $condition)
    {
        foreach (array_filter($data, function ($var) {
            return (($var !== null) && ($var !== ""));
        }) as $key => $value) {
            $query->where($key, $condition, $value);
        }
    }

    /**
     * 验证创建
     * @param $fields
     */
    protected function validateStore($fields)
    {

    }

    /**
     * 验证更新
     * @param $id
     * @param $fields
     */
    protected function validateUpdate($id, $fields)
    {

    }
}
